home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1998 / MacHack 1998.toast / The Hacks! / Interim Executive Decision / patch / (Appearance Mangler) / source code / KSwitch.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-06-21  |  6.4 KB  |  257 lines  |  [TEXT/CWIE]

  1. #include <Folders.h>
  2. #include <LowMem.h>
  3. #include "PStrings.h"
  4. #include "A4Code.h"
  5.  
  6. pascal CIconHandle    (*gOldGetCIcon)(short id);
  7. pascal PixPatHandle    (*gOldGetPixPat)(short id);
  8. short                gJGNEBusy;
  9. ProcPtr                gRealJGNEFilter;
  10. long                gLastSwitch;
  11. short                gLastIndex;
  12.  
  13. pascal CIconHandle     GetCIconPatch(short id);
  14. pascal PixPatHandle GetPixPatPatch(short id);
  15. OSErr                GetKScopeFolder(short *vRefNum, long *dirID, short *numFiles);
  16. OSErr                OpenKScopeFile(short *fNum, Boolean useLast, Boolean *alreadyOpen);
  17.  
  18. #define             DELAY_TICKS        300
  19.  
  20. /* --------------------------------------------------------------------------------    */
  21. static Boolean IsCapsLockDown(unsigned long *km)
  22. {
  23.     unsigned char    *km8 = (unsigned char *)km;
  24.     unsigned short    keycode;
  25.     short            ii, jj;
  26.     
  27.     for(ii = 0; ii < 16; ii++)
  28.         if(km8[ii])
  29.             for(jj = 0; jj < 8; jj++)
  30.                 if(km8[ii] & (1 << jj))
  31.                 {
  32.                     keycode = ii * 8 + jj;
  33.                     if(keycode == 0x39)
  34.                         return true;
  35.                 }
  36.     return false;
  37. }
  38.  
  39.  
  40. /* --------------------------------------------------------------------------------    */
  41. OSErr GetKScopeFolder(short *vRefNum, long *dirID, short *numFiles)
  42. {
  43.     OSErr    err;
  44.     
  45.     if((err = FindFolder(kOnSystemDisk, kExtensionFolderType, false, vRefNum, dirID)) == noErr)
  46.     {
  47.         CInfoPBRec    pb;
  48.         Str255        str;
  49.         static char    schemeFolder[] = "\pKaleidoscope Color Schemes";
  50.         
  51.         BlockMoveData(schemeFolder, str, schemeFolder[0] + 1);
  52.         pb.dirInfo.ioCompletion = NULL;
  53.         pb.dirInfo.ioNamePtr = str;
  54.         pb.dirInfo.ioVRefNum = *vRefNum;
  55.         pb.dirInfo.ioFDirIndex = 0;
  56.         pb.dirInfo.ioDrDirID = *dirID;
  57.         if((err = PBGetCatInfoSync(&pb)) == noErr)
  58.         {
  59.             *numFiles = pb.dirInfo.ioDrNmFls;
  60.             if(pb.hFileInfo.ioFlAttrib & 0x0010)
  61.                 *dirID = pb.dirInfo.ioDrDirID;
  62.             else
  63.                 err = fnfErr;
  64.         }
  65.     }
  66.     return err;
  67. }
  68.  
  69. /* --------------------------------------------------------------------------------    */
  70. OSErr OpenKScopeFile(short *fNum, Boolean useLast, Boolean *alreadyOpen)
  71. {
  72.     short    vRefNum, numFiles;
  73.     Str255    name;
  74.     long    dirID;
  75.     OSErr    err;
  76.     
  77.     if((err = GetKScopeFolder(&vRefNum, &dirID, &numFiles)) == noErr)
  78.     {
  79.         CInfoPBRec    pb;
  80.         
  81.         if(!useLast)
  82.             gLastIndex = ((long)Random() + 32767) * numFiles / 65536 + 1;
  83.         
  84.         pb.hFileInfo.ioCompletion = NULL;
  85.         pb.hFileInfo.ioNamePtr = name;
  86.         pb.hFileInfo.ioVRefNum = vRefNum;
  87.         pb.hFileInfo.ioFDirIndex = gLastIndex;
  88.         pb.hFileInfo.ioDirID = dirID;
  89.         if((err = PBGetCatInfoSync(&pb)) == noErr &&
  90.            !(pb.hFileInfo.ioFlAttrib & 0x0010))
  91.         {
  92.             *alreadyOpen = (pb.hFileInfo.ioFRefNum > 0);
  93.             if((*fNum = HOpenResFile(vRefNum, dirID, name, fsRdPerm)) == -1)
  94.                 err = ResError();
  95.         }
  96.         else
  97.             err = fnfErr;
  98.  
  99.         if(useLast)
  100.             gLastIndex = ((long)Random() + 32767) * numFiles / 65536 + 1;
  101.     }
  102.     return err;
  103. }
  104.  
  105. /* --------------------------------------------------------------------------------    */
  106. pascal CIconHandle GetCIconPatch(short id)
  107. {
  108.     long        oldA4;
  109.     CIconHandle    icon;
  110.     OSErr        err;
  111.     Boolean        alreadyOpen;
  112.     short        resFile;
  113.     unsigned long        keys[4];
  114.     pascal         CIconHandle    (*realproc)(short id);
  115.     
  116.     oldA4 = SetUpA4();
  117.     realproc = gOldGetCIcon;
  118.     GetKeys(keys);
  119.     if(!IsCapsLockDown(keys))
  120.         err = OpenKScopeFile(&resFile, false, &alreadyOpen);
  121.     else
  122.         err = fnfErr;
  123.     SetA4(oldA4);
  124.     
  125.     icon = realproc(id);
  126.     
  127.     if(!err)
  128.         CloseResFile(resFile);
  129.     
  130.     return icon;
  131. }
  132.  
  133. /* --------------------------------------------------------------------------------    */
  134. pascal PixPatHandle GetPixPatPatch(short id)
  135. {
  136.     long            oldA4;
  137.     PixPatHandle    pat;
  138.     OSErr            err;
  139.     Boolean            alreadyOpen;
  140.     unsigned long        keys[4];
  141.     short            resFile;
  142.     pascal             PixPatHandle    (*realproc)(short id);
  143.     
  144.     oldA4 = SetUpA4();
  145.     realproc = gOldGetPixPat;
  146.     GetKeys(keys);
  147.     if((id < -12288 || id > -12280) && !IsCapsLockDown(keys))
  148.         err = OpenKScopeFile(&resFile, true, &alreadyOpen);
  149.     else
  150.         err = fnfErr;
  151.     SetA4(oldA4);
  152.     
  153.     pat = realproc(id);
  154.     
  155.     if(!err)
  156.         CloseResFile(resFile);
  157.     
  158.     return pat;
  159. }
  160.  
  161. /* --------------------------------------------------------------------------------    */
  162. static short myGNE(EventRecord *evt, short preResult)
  163. {
  164.     OSErr                theErr;
  165.         
  166.     if(evt->what == nullEvent && LMGetTicks() > gLastSwitch + DELAY_TICKS)
  167.     {
  168.         long    value;
  169.         
  170.         Gestalt('khac', &value);
  171.         gLastSwitch = LMGetTicks();
  172.     }
  173.     return preResult;
  174. }
  175.  
  176. /* --------------------------------------------------------------------------------    */
  177. static asm void JGNEPatch(void)
  178. {
  179.     subq.l    #4,A7                // make room on the stack for gRealJGNEFilter
  180.     move.l    A4,-(A7)            // save old A4
  181.     move.l    A1,-(A7)            // save the event pointer in case we mess it up
  182.     move.l    D0,-(A7)            // save D0 because SetUpA4 uses it
  183.     jsr        SetUpA4                // point A1 at our A4
  184.     move.l    (A7)+,D0            // restore old D0
  185.     
  186.     tst.w    gJGNEBusy            // is this a reentrant call?
  187.     bne        busy
  188.     
  189.     move.w    #1,gJGNEBusy        // mark us as being busy
  190.     movem.l    A0/A2-A4/D1-D7,-(A7)// save everything just to be safe (JGNE uses D0 & A1)
  191.     move.w    D0,-(A7)            // push pre-result
  192.     move.l    A1,-(A7)            // push event record pointer
  193.     jsr        myGNE                // do the real work
  194.     addq.l    #6,A7               // pop pre-result; post-result in D0
  195.     movem.l    (A7)+,A0/A2-A4/D1-D7// restore all the regs we (probably unnecessarily) saved
  196.     move.w    D0,16(A7)            // stash result where caller expects it
  197.     move.w    #0,gJGNEBusy        // we're not busy anymore
  198.     
  199. busy:
  200.     move.l    gRealJGNEFilter,8(A7)    // get previous jGNE
  201.     move.l    (A7)+,A1            // put the event pointer back
  202.     move.l    (A7)+,A4            // restore A4
  203.     bne        leave                // rts to previous jGNE
  204.     addq.l    #4,A7                // clean up - previous jGNE was NULL
  205. leave:
  206.     rts
  207. }
  208.  
  209. /* =================================== Startup Code ===============================    */
  210.  
  211. #define    OKICON            128
  212. #define    DEADICON        129
  213.  
  214. static void ShowInit(int ID)
  215. {
  216.       Handle    showInit;
  217.       void (*ShowIcon)(short);
  218.       
  219.     if(showInit = GetResource('Code', -4048))
  220.     {
  221.         HLock(showInit);
  222.         ShowIcon = (void (*)(short))StripAddress(*showInit);
  223.         ShowIcon(ID);
  224.         HUnlock(showInit);
  225.     }
  226. }
  227.  
  228. /* --------------------------------------------------------------------------------    */
  229. void main (void)
  230. {
  231.     OSErr            theErr;
  232.     long            oldA5;
  233.     short            prefFile;
  234.     unsigned char    theKeys[16];
  235.  
  236.     EnterCodeResource();
  237.     RememberA4();
  238.     
  239.     ShowInit(OKICON);
  240.     
  241.     gJGNEBusy = 0;
  242.     gLastIndex = 1;
  243.     gLastSwitch = LMGetTicks();
  244.  
  245.     gOldGetCIcon = (pascal CIconHandle    (*)(short))NGetTrapAddress(_GetCIcon, ToolTrap);
  246.     NSetTrapAddress((UniversalProcPtr)GetCIconPatch, _GetCIcon, ToolTrap);
  247.  
  248.     gOldGetPixPat = (pascal PixPatHandle    (*)(short))NGetTrapAddress(_GetPixPat, ToolTrap);
  249.     NSetTrapAddress((UniversalProcPtr)GetPixPatPatch, _GetPixPat, ToolTrap);
  250.  
  251.     gRealJGNEFilter = (ProcPtr)LMGetGNEFilter();
  252.     LMSetGNEFilter((GNEFilterUPP)JGNEPatch);
  253.     
  254.     DetachResource(GetResource('INIT', 0));
  255.     
  256.     ExitCodeResource();
  257. }